home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Toolkit 2 / Multimedia Toolkit 2.iso / imagine / text / texture.doc < prev   
Encoding:
Text File  |  1994-05-31  |  16.2 KB  |  417 lines

  1. /*
  2. name: texture.doc
  3.  
  4.                                TEXTURE FORMAT
  5.                                --------------
  6.                        Imagine 3.0 Texture File Format
  7.  
  8.                          Rev 1.0  05-22-94 S.Kirvan
  9.                 Copyright 1994 Impulse Inc., Mpls, MN 55444
  10.  
  11.     Disclaimer:
  12.         All information contained herein is subject to change without
  13.         notice.  Knowledge is dangerous - use at your own risk.  No
  14.         warranties are made or implied, and no liability or responsibility
  15.         is assumed.     Good luck.
  16.  
  17. SCOPE:
  18. =====
  19.  
  20. This text will attempt to describe the construction of Imagine 3.0's
  21. run-time loadable texture modules.  The idea behind this text is basically,
  22. "teach by example."  By this, I mean that I have actually included and
  23. (perhaps overly) documented a texture module that does a basic, seen-it-
  24. way-too-many-times-in-raytraces, checkerboard (or checkerbored) texture.
  25. The code included is in C and all text in this document is in comment form.
  26. This document, of course, doesn't attempt to explain how Imagine 3.0's
  27. textures do what they do, but is instead, a basic example for understanding
  28. textures.
  29.  
  30. Unfortunately, Impulse does not have the support staff available to answer
  31. technical questions about the information included in this document.
  32. Hopefully, this will be basic enough to be a reasonable starting point, and
  33. at the same time, will have enough depth to leave you with a sense of
  34. direction towards more complex subjects.
  35.  
  36. Again, Good luck.
  37.  
  38.  
  39. GENERAL INFO:
  40. ============
  41.  
  42. The primary communications between the texture code and the renderer are
  43. handled through a "patch" structure.  The patch is a collection of
  44. attributes and other information that are relevent to a particular spot
  45. where a camera ray has hit an object.  This spot is refered to as the "hit
  46. point."  The information passed to the texture code by the renderer (via.
  47. the patch) can be modified to change surface attributes and create
  48. textures.  Information commonly modified by texture code is the color,
  49. transparency, reflect, and surface normals.
  50.  
  51. The functions, fwork() and iwork(), below, are the guts of the texture
  52. code.  One of these functions, fwork() for floating point and PC versions,
  53. and iwork() for Amiga integer version, is called from the renderer each
  54. time a ray hits an object with this texture on it.  The patch structure
  55. gets passed to the work function along with information about the texture
  56. axis and the position of the hit point.  Using this information, the patch
  57. may be modified, changing the object's attributes.  The texture code doesn't
  58. get any information about the "world," or about the geometry (points/edges
  59. /faces) of the object that was hit.
  60.  
  61. The entry module for the texture code is texture_init().  texture_init()
  62. sets up a structure (ttable{}) which is passed back to imagine.
  63. texture_init() also checks for software version compatability.  The
  64. structure passed back to imagine has information so that imagine can find
  65. the work() function, and the interface (the texture requester) data.
  66. Imagine's rendering code uses this pointer to the work() function when it
  67. calls the texture(s).
  68.  
  69. The section of texture.c (below), called "INITIALIZATIONS,"  sets up the
  70. data for the user interface to the textures.  This section has all the
  71. information for the text, defaults, and texture axis data that can be
  72. modified by the user.
  73.  
  74. Imagine's texture hook is intentionally as streamlined as possible - there
  75. is no error checking done within Imagine - it's all up to you.  If objects
  76. start looking bright, dark, or translucent in ways you aren't expecting,
  77. it's probably because some value has gone out of range and Imagine has
  78. forced the errant value through the renderer.  Doing this may look cool, but
  79. it could have unpredictable side effects so we recomend against doing it.
  80.  
  81. Color gun values (for color, reflect, and filter) are set by the user in a
  82. range from 0 to 255.  Within the patch, the associated color gun values are
  83. stored as floats (FRACTS) and must be normalized to range from 0.0 to 1.0.
  84.  
  85. The surface normal within the patch must also be normalized (ie. The length
  86. of the normal vector must equal 1.0).  When doing bumpy textures (like
  87. DinoSkin), you modify the surface normal to fool the renderer into putting
  88. shading and specular highlights in areas that normally wouldn't get them.
  89. As well as making sure the surface normal is normalized, you must also be
  90. sure that modifications to the surface are made relative to the local
  91. texture axis - not doing this will lead to bumps that have illogical
  92. highlights and won't animate properly.  The way to see if the bumps are
  93. being applied properly is as follows:  Create an animation with the texture
  94. in question on an object - have the camera and a light source associated to
  95. the object (so they all move in tandem). Put all these objects in black
  96. space, and rotate the main object throughout the animation.  There should
  97. be no change in the look of the object through the length of the animation
  98. since the scene is being viewed and lit relative to the object itself.  If
  99. the texture isn't doing the bumps properly, the specular highlights will
  100. crawl on the bumps.  The texture, Rainbow.itx, which was include with
  101. Imaigne 3.0 is a big help in debugging and getting bumpy textures to work
  102. properly.
  103.  
  104. In the patch, some of the data is read-only.  This data is supplied as
  105. information that can be used by the textures but modifying the data will
  106. have no effect.
  107.  
  108. When a texture is used repeatedly in the same image, it is only loaded into
  109. memory once - The important thing about this is that texture's can have
  110. static data space, but this data space will be shared by every instance of
  111. the texture.
  112.  
  113.  
  114. *********   COMPILING DETAILS   *********
  115.  
  116. The SAS/C Compiler Ver 6.5 command line is as follows:
  117.         sc nostartup code=far data=far math=68881 nostackcheck link
  118.                                                 to Texture.itx texture.c
  119. (all typed on one line...)
  120.  
  121. On the PC, the texture code has to be linked as a Phar Lap 32-bit ".REX"
  122. file (relocatable executable).  Impulse's textures were compiled using the
  123. Metaware High-C compiler, and linked using Pharlap's linker.
  124.         hc386 -Hoff=Protection -c texture.c
  125.         386link texture.obj -relexe Texture.itx
  126.  
  127. The important things to "get" about trying to compile texture code are as
  128. follows:
  129.     - don't link in startup code
  130.     - everything is 32 bit - ie. far pointers for both data and code
  131.     - don't allow the compiler to put in any stack checking code
  132.  
  133. */
  134.  
  135. /**************************************************************/
  136. /*                                                            */
  137. /*   Texture.c - Imagine 3.0 checkerboard texture example     */
  138. /*                                                            */
  139. /**************************************************************/
  140.  
  141. /*********   CONSATANTS   *********/
  142.  
  143. // constants to be used in infoflags[]
  144. #define TXTF_RED    1
  145. #define TXTF_GRN    2
  146. #define TXTF_BLU    4
  147. #define TXTF_SCL    8
  148.  
  149. // version number constant - if not correct, texture won't load
  150. #define TXT_VERS    0x49545854
  151. //#define TXT_VERS    0x54585449        // PC version
  152.  
  153. #define NULL (0L)
  154.  
  155.  
  156. /*********   DATA TYPES   *********/
  157.  
  158. typedef char                BYTE;
  159. typedef unsigned char       UBYTE;
  160. typedef short               WORD;
  161. typedef unsigned short      UWORD;
  162. typedef long                LONG;
  163. typedef void *              APTR;
  164. typedef float               FLOAT;
  165.  
  166. // FRACT can be typedef'ed as a float without harm since this example is
  167. // for the floating point version only.  See TDDD.DOC for an explanation
  168. // of the FRACT data type.
  169.  
  170. typedef float               FRACT;
  171.  
  172. typedef struct _vector {
  173.     FRACT   X;
  174.     FRACT   Y;
  175.     FRACT   Z;
  176. }   VECTOR;
  177.  
  178. typedef struct _tform   {
  179.     VECTOR  r;      // texture axes position
  180.     VECTOR  a;      // texture's X axis alignment
  181.     VECTOR  b;      // texture's Y axis alignment
  182.     VECTOR  c;      // texture's Z axis alignment
  183.     VECTOR  s;      // length of each axis
  184. }   TFORM;
  185.  
  186. // The ttable{} structure is used as a communication link between
  187. // Imagine and the run-time loadable texture modules.  This structure is
  188. // initialized and passed back to imagine by the entry module
  189. // (texture_init()).
  190.  
  191. typedef struct ttable {
  192.     LONG    id;             // version number identifier
  193.     void    (*init)();      // reserved - curently unused
  194.     void    (*cleanup)();   // reserved - curently unused
  195.     void    (*work)();      // hook to the texture algorithm (the "guts")
  196.     BYTE    **infotext;     // pointer to text fields for requester
  197.     UBYTE   *infoflags;     // pointer to data field flags for requester
  198.     APTR    params;         // pointer to data values for requester
  199.     APTR    tform;          // pointer to texture axis geometry info
  200. } TTABLE;
  201.  
  202.  
  203. // The PATCH structure contains all the (ray) hit point info.
  204. // This structure is passed to a texture function each time a
  205. // ray hits the object with a texture on it.
  206.  
  207. typedef struct _patch {
  208.     VECTOR  ptc_pos;    // global hit point - read only
  209.     VECTOR  ptc_nor;    // surface normal (must be normalized)
  210.     FRACT   ptc_col[3]; // surface color (R,G,B) at hit point
  211.     FRACT   ptc_ref[3]; // surface color (R,G,B) at hit point
  212.     FRACT   ptc_tra[3]; // surface color (R,G,B) at hit point
  213.     FRACT   ptc_spc[3]; // surface color (R,G,B) at hit point - read only
  214.     UWORD   ptc_shp;    // copy of SHAP flags - read only - see TDDD.DOC
  215.     UWORD   ptc_shd;    // flag - obj can shadow itself - read only
  216.     FRACT   ptc_pc0;
  217.     FRACT   ptc_pc1;
  218.     VECTOR  *ptc_ray;   // position/exit direction of camera ray - read only
  219.     FRACT   raydist;
  220.     FRACT   foglen;     // surface foglength
  221. }   PATCH;
  222.  
  223. // In the patch structure, ptc_ray[0] is the (camera) ray's base point
  224. // position, and ptc_ray[1] is ray's (normalized) direction vector
  225.  
  226.  
  227. /*********   PROTOTYPES   *********/
  228.  
  229. TTABLE *texture_init (LONG);
  230. void fwork (FRACT *, PATCH *, VECTOR *, FRACT *);
  231. void iwork (FRACT *, PATCH *, VECTOR *, FRACT *);
  232.  
  233.  
  234. /*********   INITIALIZATIONS   *********/
  235.  
  236. // infotext[][] is an array of strings that contain the texture name and
  237. // all the text fields that appear in the texture requester.  The
  238. // texture name file (infotext[0]) is not currently used, but we
  239. // suggest supplying a name it in case it eventually is used.
  240.  
  241. BYTE    *infotext[17] = {
  242.     "Tutorial Texture",
  243.     "Color Red",
  244.     "Color Green",
  245.     "Color Blue",
  246.     "",
  247.     "", "", "", "",
  248.     "", "", "", "",
  249.     "", "", "", "",
  250. };
  251.  
  252. // infoflags[] is an array of TXTF_ (texture flags) for the data
  253. // fields of the texture requester.  The the TXTF flags are as
  254. // follows:
  255. //      Bit 0 - alter the red gun in the requester color chip
  256. //      Bit 1 - alter the green gun in the requester color chip
  257. //      Bit 2 - alter the blue gun in the requester color chip
  258. //      Bit 3 - auto-scale this data field when object is scaled
  259. //      Bits 4 thru 7 - reserved
  260.  
  261. UBYTE   infoflags[16] = {
  262.     TXTF_RED,
  263.     TXTF_GRN,
  264.     TXTF_BLU,
  265.     0,
  266.     0, 0, 0, 0,
  267.     0, 0, 0, 0,
  268.     0, 0, 0, 0,
  269. };
  270.  
  271. // fparams[] is an array of floats that are the initial defaults
  272. // in the texture requester.  The values in this array can be
  273. // modified by the user and are passed to the texture code by
  274. // the floating point version of Imagine's renderer.
  275.  
  276. FLOAT   fparams[16] = {
  277.     255.0, 255.0, 0.0, 0.0,
  278.     0.0, 0.0, 0.0, 0.0,
  279.     0.0, 0.0, 0.0, 0.0,
  280.     0.0, 0.0, 0.0, 0.0,
  281. };
  282.  
  283. // iparams[] is an array of FRACT that are the initial defaults
  284. // in the texture requester.  The values in this array can be
  285. // modified by the user and are passed to the texture code by
  286. // the integer version (amiga only) of Imagine's renderer.  To
  287. // use FRACT with math functions requires a little creative
  288. // slight-of-hand with math macros and type conversions - doing
  289. // this is beyond the scope of this example, so the integer version
  290. // of this example texture will be stubbed out.  These are treated
  291. // as fixed point, FRACTs, stored as longs.
  292.  
  293. LONG    iparams[16] = {
  294.     0L, 0L, 0L, 0L,
  295.     0L, 0L, 0L, 0L,
  296.     0L, 0L, 0L, 0L,
  297.     0L, 0L, 0L, 0L,
  298. };
  299.  
  300. // ftform[] is an array of floats that represent the initial TFORM data
  301. // (size and position) of the texture axis.  The values in this array can
  302. // be modified by the user (via edit axis) and are passed to the texture
  303. // code by the floating point version of Imagine's renderer.
  304.  
  305. FLOAT   ftform[15] = {
  306.     0.0, 0.0, 0.0,      // position vector
  307.     1.0, 0.0, 0.0,      // X axis alignment vector
  308.     0.0, 1.0, 0.0,      // Y axis alignment vector
  309.     0.0, 0.0, 1.0,      // Z axis alignment vector
  310.     10.0, 10.0, 10.0,   // size of each axis
  311. };
  312.  
  313. // itform[] is an array of FRACT that represent the initial TFORM data
  314. // (size and position) of the texture axis.  The values in this array can
  315. // be modified by the user (via edit axis) and are passed to the texture
  316. // code by the integer version of Imagine's renderer.  Again, this example
  317. // is for floating point systems only.  The FRACT data type is explained
  318. // in TDDD.DOC and the integer version of this texture example will be
  319. // stubbed out.  These are treated as fixed point, FRACTs, stored as longs.
  320.  
  321. LONG    itform[15] = {
  322.     0L, 0L, 0L,
  323.     0L, 0L, 0L,
  324.     0L, 0L, 0L,
  325.     0L, 0L, 0L,
  326.     10*0x10000L, 10*0x10000L, 10*0x10000L,
  327. };
  328.  
  329. // this ttable{} structure is defined earlier and initialized here.
  330.  
  331. TTABLE ttable = {
  332.     TXT_VERS,       /* version identifier - this contstant must be used */
  333.     NULL,
  334.     NULL,
  335.     NULL,
  336.     infotext,
  337.     infoflags,
  338. };
  339.  
  340.  
  341. /*********   FUNCTIONS   *********/
  342.  
  343. // This is the texture_init() module for the textures.  This is the entry
  344. // module through which Imagine loads and calls the texture code.
  345. // texture_init() is called with a version number and a flag representing
  346. // whether this texture is being called from a floating point version or an
  347. // integer version of Imagine.  On the Amiga, these two (WORD) arguments
  348. // are packed into and passed as a single LONG which, in turn, is parsed
  349. // into the two arguments and interpreted within texture_init(). If all
  350. // goes well, texture_init() then initializes the ttable{} structure
  351. // (defined above) with the proper info and returns a pointer, for the
  352. // ttable{} structure, back to Imagine.
  353.  
  354. TTABLE *texture_init (LONG arg0)
  355. {
  356.     // "TTABLE *texture_init (int vers, int fp)" on PC
  357.  
  358.     WORD    vers, fp;
  359.  
  360.     vers = arg0 >> 16;      // parse out the two arguments
  361.     fp = arg0 & 0xffff;
  362.  
  363.     if(vers != 0x60)        // look for wrong version number
  364.         return 0L;
  365.  
  366.     if (fp) {      // called from the floating point version
  367.         ttable.work = fwork;
  368.         ttable.params = (APTR)fparams;
  369.         ttable.tform = (APTR)ftform;
  370.     } else {      // called from the (Amiga only) integer version
  371.         ttable.work = iwork;
  372.         ttable.params = (APTR)iparams;
  373.         ttable.tform = (APTR)itform;
  374.     }
  375.     return &ttable;
  376. }
  377.  
  378.  
  379.  
  380. void fwork(params, pt, v, t)    // this is the floating point work function.
  381. FRACT *params;          // pointer to user definable numbers in requester
  382. PATCH *pt;              // pointer to patch structure - defined above
  383. VECTOR *v;              // hit position  -  relative to texture axis
  384. FRACT *t;               // info about texture axis (TFORM array - 15 floats)
  385. {
  386.     FLOAT X, Y, Z;
  387.  
  388.     X = v->X / t[12];  // note that the texture axis is used for scaling
  389.     Y = v->Y / t[13];
  390.     Z = v->Z / t[14];
  391.  
  392.     if (X < 0.0) X -= 1.0; // this eliminates duplication across the axes
  393.     if (Y < 0.0) Y -= 1.0; // as the chex go from the posative to the
  394.     if (Z < 0.0) Z -= 1.0; // negative regions
  395.  
  396.     if (((int)X + (int)Y + (int)Z) % 2) { // check for even numbers
  397.         pt->ptc_col[0] = params[0] * .00392157; // use the params from
  398.         pt->ptc_col[1] = params[1] * .00392157; // the requester on
  399.         pt->ptc_col[2] = params[2] * .00392157; // these chex.
  400.     } else {
  401.         pt->ptc_col[0] = 0.0;   // force the others to be blue
  402.         pt->ptc_col[1] = 0.0;
  403.         pt->ptc_col[2] = 0.5;
  404.     }
  405.  
  406. }
  407.  
  408.  
  409. void iwork(params, pt, v, t)   // This is the integer version work function.
  410. FRACT *params;
  411. PATCH *pt;
  412. VECTOR *v;
  413. FRACT *t;
  414. {
  415.     ;   // stub...
  416. }
  417.